import { Component, OnInit, AfterViewInit, Host, ViewChild, ElementRef } from '@angular/core';
import { Router, ActivatedRoute } from '@angular/router';
import { HttpEvent, HttpResponse } from '@angular/common/http';
import { AppComponent } from '../../app.component';
import { AuthenticationService } from './login.service';
import { StorageService } from '../../shared/services/storage.service';
import { NgxSmartModalService } from 'ngx-smart-modal';
import { AnalyticsService } from '../../shared/services/googleAnalytics.service';
import { GoogleAnalyticsBeacon } from '../../shared/models/googleAnalytics.model';
import { TokenModel } from './models/token.model';
import { SignalRService } from '../../shared/services/signalR.service';
import { UtilsService } from '../../shared/services/utils.service';
import { CookieService } from 'ngx-cookie-service';
import * as crypto from 'crypto-js';

/**
 * Login main component
 *
 * Author: Sorin Spiru, Andrei Istrate
 * Date: 13.01.2018
 */
@Component({
    moduleId: module.id,
    templateUrl: 'login.component.html',
    providers: [StorageService],
    styleUrls: ['./login.component.scss']
})
export class LoginComponent implements OnInit, AfterViewInit {
    @ViewChild('passwordField') passwordField: ElementRef;
    private cookieName: string = 'sustainalyticsGlobalAccess';    
    private cookieCredenials: string = '_credentials';
    private aesKey = 'sustain2019';
    public model: any = {};
    public error = false;
    public resetPass = false;
    public showPass = false;
    public agreementType: string;
    public ipLoginUsername: string;
    public returnUrl: string;
    public errorMessage: string;
    public rememberMe: boolean = false;

    constructor(
        private router: Router,
        private authenticationService: AuthenticationService,
        private ngxSmartModalService: NgxSmartModalService,
        private analyticsService: AnalyticsService,
        private signalRService: SignalRService,
        @Host() private rootComponent: AppComponent,
        private route: ActivatedRoute,
        private cookieService: CookieService
    ) { }

    ngOnInit() {
        // reset login status
        this.authenticationService.logout();
        this.signalRService.disconnect();

        // get return url from route parameters or default to '/home'
        this.returnUrl = this.route.snapshot.queryParams['returnUrl'] || '/home';

        if (this.router.url == '/login/ip') {
            this.authenticationService.ipLogin().subscribe(
                (result: any) => {
                    this.ipLoginUsername = result.headers.get('username');
                    this.parseLoginResult(result.body, true);
                },
                err => {
                    this.error = true;
                }
            );
        }

        //load remember me credentials
        if (this.cookieService.check(this.cookieName + this.cookieCredenials)) {
            this.rememberMe = true;
            let bytes = crypto.AES.decrypt(this.cookieService.get(this.cookieName + this.cookieCredenials), this.aesKey);
            let credentials = JSON.parse(bytes.toString(crypto.enc.Utf8));
            this.model.username = credentials.username;
            this.model.password = credentials.password;
        }        
    }

    ngAfterViewInit() {
        this.rootComponent.finishLoading();
    }

    login() {
        if (UtilsService.IsValidEmail(this.model.username)) {
            this.authenticationService.login(this.model.username, this.model.password).subscribe(
                result => this.parseLoginResult(result),
                err => {
                    this.error = true;
                    this.errorMessage = "Invalid Credentials";
                }
            );
        }
        else {
            this.error = true;
            this.errorMessage = "Please enter a valid email address";
        }

    }

    public rememberToggle() {
        if (this.rememberMe == false) {
            this.cookieService.delete(this.cookieName + this.cookieCredenials);
        }
    }

    private parseLoginResult(result: HttpEvent<TokenModel>, ipLogin: boolean = false) {
        if (result && result['access_token']) { // login successful               
            if (ipLogin) this.authenticationService.saveToken(result);
            if (this.rememberMe == true) this.cookieService.set(this.cookieName + this.cookieCredenials, crypto.AES.encrypt(JSON.stringify({ username: this.model.username, password: this.model.password }), this.aesKey));
            this.finalizeLogin();
        } else if (result && result['error']) { // login failed

            switch (result['error']['error']) {
                case 'ClientLegalAgreementNotAccepted':
                    this.agreementType = 'client';
                    this.ngxSmartModalService.getModal('termsAgreementModal').open();
                    break;
                case 'ProspectLegalAgreementNotAccepted':
                    this.agreementType = 'prospect';
                    this.ngxSmartModalService.getModal('termsAgreementModal').open();
                    break;
                case 'IncorrectUsernamePasswordCombination':
                default:
                    this.error = true;
                    this.errorMessage = "Invalid Credentials";
                    break;
            }
        } else
            this.error = true;
    }

    logout() {
        this.authenticationService.logout();
        this.signalRService.disconnect();
        this.ngxSmartModalService.getModal('termsAgreementModal').close();
    }

    public toggleShowPassword(): void {
        this.showPass = !this.showPass;
        this.passwordField.nativeElement.type = this.showPass ? 'text' : 'password';
    }

    agreeToTerms(): void {
        this.authenticationService
            .acceptLegalAgreement(this.router.url == '/login/ip' ? this.ipLoginUsername : this.model.username)
            .subscribe(_ => {
                this.login();
                this.ngxSmartModalService.getModal('termsAgreementModal').close();
            });
    }

    private finalizeLogin(): void {
        // set auth object
        this.authenticationService.permissions().subscribe(data => {
            //if iplogin, remove the portfolio alert subscriptions
            if (this.router.url == '/login/ip')
                data = data.filter(x => x.resource !== 'api/v1/subscribetoportfolio');

            // set permissions
            StorageService.get().resourcePermissions = data;
            this.authenticationService.profile().subscribe(userInfo => {
                // set user info
                StorageService.get().userInfo = userInfo;
                this.analyticsService.config();
                this.analyticsService.sendBeacon(new GoogleAnalyticsBeacon('User logged in', 'Login', {}));
                this.router.navigateByUrl(this.returnUrl);
            });
        });
    }
}
